package com.zzx.config;

import com.zzx.bean.Color;
import com.zzx.bean.ColorFactoryBean;
import com.zzx.bean.Person;
import com.zzx.bean.Red;
import com.zzx.condition.LinuxCondition;
import com.zzx.condition.MyImportBeanDefinitionRegistrar;
import com.zzx.condition.MyImportSelector;
import com.zzx.condition.WindowsCondition;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.*;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;

/**
 * config2
 *
 * @author Jesse
 * @version 1.0
 * @date 2021/06/12
 */
@Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})//@Import 导入组件，id默认是组件的全类名
@Configuration
public class MainConfig2 {


    /**
     * 给容器中注册一个 bean，类型为返回值类型，id 默认是方法名作为 id
     * 可以在 @Bean 中设置 bean 的名称
     *
     * @see ConfigurableBeanFactory#SCOPE_PROTOTYPE
     * @see ConfigurableBeanFactory#SCOPE_SINGLETON
     * @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST
     * @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION
     * @Scope 调整作用域
     * <p>
     * prototype：多实例。 IOC容器启动并不会去调用方法创建对象放在容器中。
     *          每次获取的时候才会调用方法创建对象。
     * singleton：单实例（默认值）。IOC容器启动就会调用方法创建对象放到IOC容器中。
     *          以后每次获取就是直接从容器（map.get()）中拿
     * request：同一个请求创建一个实例
     * session：同一个 session 创建一个实例
     *
     * 懒加载：@Lazy
     *      单实例bean：默认在容器启动的时候创建对象；
     *      懒加载：容器启动不创建对象。第一次使用（获取）Bean创建对象，并初始化；
     */
    @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
    @Bean("person")
    public Person getPerson() {
        System.out.println("给容器中添加 Person");
        return new Person("zzx", 28);
    }

    /**
     * @Conditional:按照一定的条件进行判断，满足条件给容器中注册bean 如果系统是 Windows 系统，给容器中注册("bill")
     * 如果系统是 linux 系统，给容器中注册("linus")
     */
    @Conditional({WindowsCondition.class})
    @Bean("bill")
    public Person person01() {
        return new Person("Bill Gates", 62);
    }


    @Conditional({LinuxCondition.class})
    @Bean("linus")
    public Person person02() {
        return new Person("Linus", 58);
    }

    /**
     * 给容器中注册组件
     * 1）、包扫描 + 组件标注注解（@Controller/@Service/@Repository/@Component）自己写的类;
     * 2）、@Bean[导入的第三方包里面的组件];
     * 3）、@Import[快速给容器导入一个组件]
     *      a、@Import(要导入到容器中的组件)；容器中就会自动注册这个组件，id 默认就是全类名;
     *      b、@ImportSelector：返回需要导入的组件的全类名数组;
     *      c、@ImportBeanDefinitionRegistrar：手动注册 bean 到容器中;
     * 4）、使用 spring 提供的 FactoryBean （工厂Bean）;
     *      a、默认获取到的是工厂 bean 调用 getObject 创建的对象
     *      b、要获取工厂 bean 本身，我们需要给 id 前面加个&，&colorFactoryBean
     */
    @Bean
    public ColorFactoryBean colorFactoryBean() {
        return new ColorFactoryBean();
    }


}
